package cn.izeno.wx.service

import cn.izeno.wx.models.component.*
import io.reactivex.rxjava3.core.Observable
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query
import java.io.File


/**
 * 微信开放平台接口
 */
interface ComponentService {

  //<editor-fold desc="开放平台授权流程">
  /**
   * ### 2、获取第三方平台component_access_token
   *
   * 获取第三方平台component_access_token
   * 第三方平台component_access_token是第三方平台的下文中接口的调用凭据，
   * 也叫做令牌（component_access_token）。每个令牌是存在有效期（2小时）的，
   * 且令牌的调用不是无限制的，请第三方平台做好令牌的管理，在令牌快过期时（比如1小时50分）再进行刷新。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_component_token")
  fun componentToken(@Body body: ComponentTokenParam): Observable<ComponentToken>

  /**
   * ### 3、获取预授权码pre_auth_code
   * 该API用于获取预授权码。预授权码用于公众号或小程序授权时的第三方平台方安全验证。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode")
  fun preAuthCode(
      @Body body: AppPreAuthCodeParam,
      @Query("component_access_token")
      token: String = ComponentApp.accessToken
  ): Observable<AppPreAuthCode>

  /**
   * ### 4、使用授权码换取公众号或小程序的接口调用凭据和授权信息
   *
   * 该API用于使用授权码换取授权公众号或小程序的授权信息，
   * 并换取authorizer_access_token和authorizer_refresh_token。
   * 授权码的获取，需要在用户在第三方平台授权页中完成授权流程后，
   * 在回调URI中通过URL参数提供给第三方平台方。
   * 请注意，由于现在公众号或小程序可以自定义选择部分权限授权给第三方平台，
   * 因此第三方平台开发者需要通过该接口来获取公众号或小程序具体授权了哪些权限，
   * 而不是简单地认为自己声明的权限就是公众号或小程序授权的权限。
   *
   * @param token 第三方公众平台的 messageToken
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_query_auth")
  fun accessToken(
      @Body body: AppAuthParam,
      @Query("component_access_token") token: String = ComponentApp.accessToken
  ): Observable<AppAuth>

  /**
   * #### 5、获取（刷新）授权公众号或小程序的接口调用凭据（令牌）
   *
   * 该API用于在授权方令牌（authorizer_access_token）失效时，
   * 可用刷新令牌（authorizer_refresh_token）获取新的令牌。
   * 请注意，此处token是2小时刷新一次，开发者需要自行进行token的缓存，
   * 避免token的获取次数达到每日的限定额度。[缓存方法可以参考](http://mp.weixin.qq.com/wiki/2/88b2bf1265a707c031e51f26ca5e6512.html)
   * 当换取authorizer_refresh_token后建议保存。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token")
  fun authToken(
      @Body body: AppTokenParam,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<AppToken>

  /**
   * #### 6、获取授权方的帐号基本信息
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info")
  fun appInfo(
      @Body body: AppInfoParam,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<AppInfo>


  /**
   * #### 7、获取授权方的选项设置信息
   * 该API用于获取授权方的公众号或小程序的选项设置信息，
   * 如：地理位置上报，语音识别开关，多客服开关。
   * 注意，获取各项选项设置信息，需要有授权方的授权，详见权限集说明。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option")
  fun getOption(
      @Body body: AppOptionParam,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<AppOption>

  /**
   * #### 8、设置授权方的选项信息
   * 该API用于设置授权方的公众号或小程序的选项信息，
   * 如：地理位置上报，语音识别开关，多客服开关。
   * 注意，设置各项选项设置信息，需要有授权方的授权，详见权限集说明。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/api_set_authorizer_option")
  fun setOption(
      @Body body: AppOptionParam,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<AppOption>
  //</editor-fold>

  @POST("https://api.weixin.qq.com/cgi-bin/component/fastregisterweapp?action=create")
  fun weappFastRegister(
      @Body body: FastCreateWeappInfo,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<BaseRes>


  /**
   * 二、查询创建任务状态
   * #### Tips
   *
   * [body]
   *
   * ```json
   * {
   *   "name": "tencent",               // 企业名
   *   "legal_persona_wechat": "123",   // 法人微信
   *   "legal_persona_name":"pony" ,    // 法人姓名
   * }
   * ```
   */
  @POST("https://api.weixin.qq.com/cgi-bin/component/fastregisterweapp?action=search")
  fun weappFastRegisterSearch(
      @Body body: FastCreateWeappInfo,
      @Query("component_access_token")
      accessToken: String = ComponentApp.accessToken
  ): Observable<BaseRes>


  /**
   * # 代小程序实现业务
   * ### [小程序代码模版库管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1506504150_nMMh6&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 1、获取草稿箱内的所有临时代码草稿
   *
   */
  @GET("https://api.weixin.qq.com/wxa/gettemplatedraftlist")
  fun weappDraftList(@Query("access_token") accessToken: String = ComponentApp.accessToken): Observable<TempWeappRes>


  /**
   * # 代小程序实现业务
   * ### [小程序代码模版库管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1506504150_nMMh6&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 2、获取代码模版库中的所有小程序代码模版
   */
  @GET("https://api.weixin.qq.com/wxa/gettemplatelist")
  fun weappTemplateList(@Query("access_token") accessToken: String = ComponentApp.accessToken): Observable<TempWeappRes>

  /**
   * # 代小程序实现业务
   * ### [小程序代码模版库管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1506504150_nMMh6&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 3、将草稿箱的草稿选为小程序代码模版
   */
  @POST("https://api.weixin.qq.com/wxa/addtotemplate")
  fun weappAddTemplate(
      @Body body: WeappDraftId,
      @Query("access_token") accessToken: String = ComponentApp.accessToken
  ): Observable<BaseRes>

  /**
   * # 代小程序实现业务
   * ### [小程序代码模版库管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1506504150_nMMh6&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 3、将草稿箱的草稿选为小程序代码模版
   */
  @POST("https://api.weixin.qq.com/wxa/deletetemplate")
  fun weappDeleteTemplate(
      @Body body: WeappTemplatetId,
      @Query("access_token") accessToken: String = ComponentApp.accessToken
  ): Observable<BaseRes>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 1、为授权的小程序帐号上传小程序代码
   */
  @POST("https://api.weixin.qq.com/wxa/commit")
  fun weappCommit(
      @Body body: WeappCommit,
      @Query("access_token") appAccessToken: String
  ): Observable<BaseRes>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 2. 获取体验小程序的体验二维码
   */
  @GET("https://api.weixin.qq.com/wxa/get_qrcode")
  fun weappQrcode(
      @Query("path") uriEncodedPath: String = "",
      @Query("access_token") appAccessToken: String
  ): Observable<File>

  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 3. 获取授权小程序帐号已设置的类目
   * > 注意：该接口可获取已设置的二级类目及用于代码审核的可选三级类目。
   */
  @GET("https://api.weixin.qq.com/wxa/get_category")
  fun weappCategory(@Query("access_token") appAccessToken: String): Observable<WeappCategoryRes>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 4、获取小程序的第三方提交代码的页面配置（仅供第三方开发者代小程序调用）
   */
  @GET("https://api.weixin.qq.com/wxa/get_page")
  fun weappPages(@Query("access_token") appAccessToken: String): Observable<WeappPages>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * 5、将第三方提交的代码包提交审核（仅供第三方开发者代小程序调用）
   */
  @POST("https://api.weixin.qq.com/wxa/submit_audit")
  fun weappSubmitAudit(
      @Body body: WeappSubmit,
      @Query("access_token") appAccessToken: String
  ): Observable<BaseRes>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * `15. 小程序审核撤回`
   * - __单个帐号每天审核撤回次数最多不超过1次，一个月不超过10次。__
   */
  @GET("https://api.weixin.qq.com/wxa/undocodeaudit")
  fun weappUndoCodeAudit(@Query("access_token") appAccessToken: String): Observable<BaseRes>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * `8、查询最新一次提交的审核状态（仅供第三方代小程序调用）`
   */
  @GET("https://api.weixin.qq.com/wxa/get_latest_auditstatus")
  fun weappLatestAuditStatus(@Query("access_token") appAccessToken: String): Observable<WeappAudit>

  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * `9、发布已通过审核的小程序（仅供第三方代小程序调用）`
   */
  @POST("https://api.weixin.qq.com/wxa/release")
  fun weappRelease(@Query("access_token") appAccessToken: String, @Body body: Any = Any()): Observable<BaseRes>


  //<editor-fold desc="小程序信息设置">


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 1 获取帐号基本信息
   *
   * - 快速创建的小程序可访问该接口
   */
  @GET("https://api.weixin.qq.com/cgi-bin/account/getaccountbasicinfo")
  fun weappInfo(@Query("access_token") appAccessToken: String): Observable<AppBaseInfo>


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 2 小程序名称设置及改名
   */
  @POST("https://api.weixin.qq.com/wxa/setnickname")
  fun weappSetNickname(
      @Body body: WeappNickname,
      @Query("access_token") appAccessToken: String
  ): Observable<NicknameAudit>


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 3 小程序改名审核状态查询
   *
   * ```
   * {
   *   "audit_id":12345
   * }
   * ```
   */
  @POST("https://api.weixin.qq.com/wxa/api_wxa_querynickname")
  fun weappNicknameVerifyStatus(
      @Body body: NicknameAudit,
      @Query("access_token") appAccessToken: String
  ): Observable<NicknameAudit>

  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 4 微信认证名称检测
   *
   * ```
   * {
   *   "nick_name": "杨幂的测试用例",
   * }
   * ```
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxverify/checkwxverifynickname")
  fun weappNicknameCheck(
      @Body body: WeappNickname,
      @Query("access_token") appAccessToken: String
  ): Observable<NicknameCheck>


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 5 修改头像
   */
  @POST("https://api.weixin.qq.com/cgi-bin/account/modifyheadimage")
  fun weappModifyHeadimg(
      @Body body: WeappHeadimg,
      @Query("access_token") appAccessToken: String
  ): Observable<BaseRes>


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * ### 6 修改功能介绍
   */
  @POST("https://api.weixin.qq.com/cgi-bin/account/modifysignature")
  fun weappModifySignature(
      @Body body: Signature,
      @Query("access_token") appAccessToken: String
  ): Observable<BaseRes>

  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * 8.1 获取账号可以设置的所有类目
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxopen/getallcategories")
  fun weappAllCategory(@Query("access_token") appAccessToken: String): Observable<WeappAllCate>


  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * 8.2添加类目
   *
   * ```
   * {
   *   “categories”: [{
   *     “first”: 8,
   *     “second”: 39,
   *     “certicates”: [{
   *       “key”: ”《因私出入境中介机构经营许可证》”,
   *       “value”: ”xxx”
   *     }]
   *   }]
   * }
   * ```
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxopen/addcategory")
  fun weappAddCategory(@Body body: AddCategoryFC, @Query("access_token") appAccessToken: String): Observable<BaseRes>

  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * 8.3删除类目
   * ```
   * {
   *   “first”: 8,
   *   “second”: 39,
   * }
   * ```
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxopen/deletecategory")
  fun weappDeleteCategoryFC(@Body body: AddCategoryFC.Category, @Query("access_token") appAccessToken: String): Observable<BaseRes>

  /**
   * # [小程序信息设置](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&id=21528465979XX32V)
   * 8.4 获取账号已经设置的所有类目
   */
  @GET("https://api.weixin.qq.com/cgi-bin/wxopen/getcategory")
  fun weappCategoryFC(@Query("access_token") appAccessToken: String): Observable<WeappCategoryFC>
  //</editor-fold>

  @POST("https://api.weixin.qq.com/wxa/modify_domain")
  fun weappModifyDomain(
      @Body body: WeappDomain,
      @Query("access_token") appAccessToken: String
  ): Observable<WeappDomain>

  @POST("https://api.weixin.qq.com/wxa/setwebviewdomain")
  fun weappModifyWebviewDomain(
      @Body body: WeappDomain,
      @Query("access_token") appAccessToken: String
  ): Observable<WeappDomain>


  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * #### 12. 查询当前设置的最低基础库版本及各版本用户占比（仅供第三方代小程序调用）
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion")
  fun weappSdkVersion(@Query("access_token") appAccessToken: String, @Body body: Any = Any()): Observable<WeappSdkVersion>

  /**
   * # 代小程序实现业务 - [代码管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=f56e40a289a959318cef6ca35d38e9eaf15e6d33&lang=zh_CN)
   * #### 13. 设置最低基础库版本（仅供第三方代小程序调用）
   */
  @POST("https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion")
  fun weappSetSdkVersion(
      @Body body: SdkVersion,
      @Query("access_token") appAccessToken: String
  ): Observable<BaseRes>


  /**
   * # 带小程序实现业务 - [成员管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1489140588_nVUgx)
   * #### 绑定微信用户为小程序体验者
   */
  @POST("https://api.weixin.qq.com/wxa/bind_tester")
  fun weappBindTester(@Body body: WeappTester, @Query("access_token") appAccessToken: String): Observable<WeappTester>

  /**
   * # 带小程序实现业务 - [成员管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1489140588_nVUgx)
   * #### 2、解除绑定小程序的体验者
   *
   * @param body [WeappTester.wechatid]和[WeappTester.userstr]填写其中一个即可
   */
  @POST("https://api.weixin.qq.com/wxa/unbind_tester")
  fun weappUnbindTester(@Body body: WeappTester, @Query("access_token") appAccessToken: String): Observable<BaseRes>


  /**
   * # 带小程序实现业务 - [成员管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1489140588_nVUgx)
   * #### 3. 获取体验者列表
   */
  @POST("https://api.weixin.qq.com/wxa/memberauth")
  fun weappTester(
      @Query("access_token") appAccessToken: String,
      @Body body: WeappTesterGet = WeappTesterGet()
  ): Observable<WeappTesterList>


  /**
   * # 带小程序实现业务 - [微信开放平台帐号管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1498704199_1bcax)
   * #### 1 、 创建 开放平台帐号并绑定公众号/小程序
   */
  @POST("https://api.weixin.qq.com/cgi-bin/open/create")
  fun openCreate(@Body body: Appid, @Query("access_token") appAccessToken: String): Observable<OpenAppid>

  /**
   * # 带小程序实现业务 - [微信开放平台帐号管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1498704199_1bcax)
   * #### 2 、 将 公众号/小程序绑定到开放平台帐号下
   *
   * 该API用于将一个尚未绑定开放平台帐号的公众号或小程序绑定至指定开放平台帐号上。二者须主体相同。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/open/bind")
  fun openBind(@Body body: OpenBind, @Query("access_token") appAccessToken: String): Observable<BaseRes>


  /**
   * # 带小程序实现业务 - [微信开放平台帐号管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1498704199_1bcax)
   * #### 3、将公众号/小程序从开放平台帐号下解绑
   *
   * 该API用于将一个公众号或小程序与指定开放平台帐号解绑。开发者须确认所指定帐号与当前该公众号或小程序所绑定的开放平台帐号一致。
   */
  @POST("https://api.weixin.qq.com/cgi-bin/open/unbind")
  fun openUnbind(@Body body: OpenBind, @Query("access_token") appAccessToken: String): Observable<BaseRes>


  /**
   * # 待小程序实现业务 - [微信开放平台帐号管理](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&id=open1498704199_1bcax)
   * #### 4、获取公众号/小程序所绑定的开放平台帐号
   */
  @POST("https://api.weixin.qq.com/cgi-bin/open/get")
  fun openGet(@Body body: Appid, @Query("access_token") appAccessToken: String): Observable<OpenAppid>
}
